﻿using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;
using Abp.Linq.Extensions;
using Hicap.AuthorizationServer.Application.Dto.Common;
using Hicap.AuthorizationServer.Application.Helper;
using Hicap.AuthorizationServer.Core.Identity;
using Hicap.AuthorizationServer.Core.Managers;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Hicap.AuthorizationServer.Application
{
    [HicapAuthorize]
    public abstract class AuthorizationServerApplicationBase<TEntity, TEntityListDto, TEntityEditDto> : IAuthorizationServerApplicationBase<TEntityListDto, TEntityEditDto> where TEntity : class, IEntity, ISoftDelete
        where TEntityListDto : class, IFullAudited
        where TEntityEditDto : class, IEntityDto<int?>
    {
        private readonly IManagerBase<TEntity> _manager;

        protected AuthorizationServerApplicationBase(IManagerBase<TEntity> manager) : base()
        {
            _manager = manager;
        }

        public IQueryable<TEntity> GetQuery(IQueryable<TEntity> query, QueryInput queryInput = null)
        {
            return GetQueryBuilder(query, queryInput);
        }

        private IQueryable<TEntity> GetQueryBuilder(IQueryable<TEntity> query, QueryInput queryInput = null)
        {
            //根据传入的参数添加过滤条件
            System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = queryInput != null ?
                ExpressionHelper<TEntity>.CreateExpression(queryInput?.Filter) : null;

            IQueryable<TEntity> queryable = filter != null ? query.Where(filter) : query;
            return queryable.AsNoTracking();
        }

        public virtual async Task<PagedResultDto<TEntityListDto>> PagedDatas(QueryInput queryInput)
        {
            IQueryable<TEntity> query = GetQuery(_manager.GetQuery(null), queryInput);

            int count = query.Count();

            List<TEntity> result = await query
                .OrderBy(queryInput.Sorting)
                .PageBy(queryInput)
                .ToListAsync();

            List<TEntityListDto> resultListDto = result.MapTo<List<TEntityListDto>>();

            return new PagedResultDto<TEntityListDto>(
                count,
                resultListDto
            );
        }

        public virtual async Task<TEntityListDto> GetById(int input)
        {
            TEntity dbEntity = await _manager.GetQuery(null).FirstOrDefaultAsync(x => x.Id == input);
            TEntityListDto entity = dbEntity.MapTo<TEntityListDto>();
            return entity;
        }

        public virtual async Task<int> UpsertAsync(CreateOrUpdateInput<TEntityEditDto> input)
        {
            TEntity entity = input.Entity.MapTo<TEntity>();

            return await _manager.InsertOrUpdate(entity);
        }

        public virtual async Task<int> BatchUpsert(List<CreateOrUpdateInput<TEntityEditDto>> inputs)
        {
            List<TEntity> list = inputs.MapTo<List<TEntity>>();
            return await _manager.BatchInsertOrUpdate(list);
        }

        public virtual async Task<int> Delete(int input)
        {
            return await _manager.Delete(input);
        }

        public virtual async Task<int> BatchDelete(List<int> input)
        {
            return await _manager.BatchDelete(input);
        }
    }
}